package cn.dev.mybatis.handler.executor;

import cn.dev.mybatis.bean.SqlObject;
import cn.dev.mybatis.handler.ResultHandler;
import cn.dev.mybatis.handler.result.BeanResultHandler;
import cn.dev.mybatis.handler.result.MapResultHandler;
import cn.dev.mybatis.handler.result.ObjectResultHandler;
import cn.dev.mybatis.util.ClassUtils;

import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

public class SelectSqlExecutor extends AbstractSqlExecutor {
    public SelectSqlExecutor(SqlObject sqlObject) {
        super(sqlObject);
    }

    @Override
    public Object execute(Connection connection) throws SQLException {
        String originSql = sqlObject.getOriginSql();
        PreparedStatement ps = connection.prepareStatement(originSql);
        addParam(ps, sqlObject.getParamValue());
        ResultSet rs = ps.executeQuery();
        Type retureType = sqlObject.getRetureType();

        // 处理基础数据类型
        if (ClassUtils.isPrimaryClass(retureType)) {
            return rs.getObject(1);
        }

        ResultSetMetaData metaData = rs.getMetaData();
        int columnCount = metaData.getColumnCount();

        // 处理List类型
        if (retureType == List.class) {
            ArrayList<Object> result = new ArrayList<>();
            // 解析泛型
            Type type = sqlObject.getActualReturnType()[0];
            if (ClassUtils.isPrimaryClass(type)) {
                while (rs.next()) {
                    result.add(parseResult(new ObjectResultHandler(), rs, columnCount));
                }
                return result;
            }
            if (type instanceof ParameterizedType parameterizedType && parameterizedType.getRawType() == Map.class) {
                while (rs.next()) {
                    result.add(parseResult(new MapResultHandler(), rs, columnCount));
                }
                return result;
            }

            while (rs.next()) {
                result.add(parseResult(new BeanResultHandler<>(type), rs, columnCount));
            }
            return result;
        }

        // 处理Map类型
        if (retureType == Map.class) {
            if (rs.next()) {
                return parseResult(new MapResultHandler(), rs, columnCount);
            }
        }

        // 处理bean
        if (rs.next()) {
            return parseResult(new BeanResultHandler<>(retureType), rs, columnCount);
        }
        return null;
    }

    private <T> T parseResult(ResultHandler<T> resultHandler, ResultSet rs, int column) throws SQLException {
        return resultHandler.handle(rs, column);
    }
}
